/* 
 * File:   ArchivoPalabraAleatoria.cpp
 * Author: martin
 * 
 * Created on September 18, 2012, 10:51 AM
 */

#include "ArchivoPalabraAleatoria.h"
#include<cstring>
#include<unistd.h>
#include<sys/types.h>
#include<iostream>
#include<cstdlib>

using std::string;

void ArchivoPalabraAleatoria::cerrarEscritura(){
    if(!salida->is_open())
        return;
    
    salida->seekp(0,ofstream::end);
    salida->close();
    this->cantidadRegistros= 0;
    this->posicionArchivo= 0;
}//cerrarEscritura

void ArchivoPalabraAleatoria::cerrarLectura(){
    if(!entrada->is_open())
        return;
    
    entrada->seekg(0,ofstream::end);
    entrada->close();
    this->cantidadRegistros= 0;
    this->posicionArchivo= 0;
}//cerrarLectura

void ArchivoPalabraAleatoria::cerrar(){
    this->cerrarEscritura();
    this->cerrarLectura();
}//cerrar

unsigned long ArchivoPalabraAleatoria::getTamanioArchivo(){
    unsigned long tamanio= 0;
    
    if(salida->is_open()){
        salida->seekp(0,ofstream::end);
        tamanio= salida->tellp();
        salida->seekp(posicionArchivo,ofstream::beg);
    }else
        if(entrada->is_open()){
            entrada->seekg(0,ofstream::end);
            tamanio= entrada->tellg();
            entrada->seekg(posicionArchivo,ofstream::beg);            
        }
    
    return tamanio;
}//getTamanioArchivo

int ArchivoPalabraAleatoria::abrirEscritura(char* direccionArchivo){
    if(!direccionArchivo)
        return PalabraAleatoria::DIR_ERRONEA;
    
    this->cerrar();
    salida->open(direccionArchivo,ofstream::app);
    if(!salida->is_open())
        return PalabraAleatoria::ARCH_INVALIDO;
    
    posicionArchivo= this->getTamanioArchivo();
    cantidadRegistros= posicionArchivo/PalabraAleatoria::TAM_REGISTRO;
    strcpy(pathArchivo,direccionArchivo);
    
    return PalabraAleatoria::EXITO;
}//abrirEscritura

int ArchivoPalabraAleatoria::abrirLectura(char* direccionArchivo){
    if(!direccionArchivo)
        return PalabraAleatoria::DIR_ERRONEA;
    
    this->cerrar();
    entrada->open(direccionArchivo,ifstream::binary);
    if(!entrada->is_open())
        return PalabraAleatoria::ARCH_INVALIDO;
    
    posicionArchivo= 0;
    cantidadRegistros= this->getTamanioArchivo()/PalabraAleatoria::TAM_REGISTRO;
    strcpy(pathArchivo,direccionArchivo);
    
    return PalabraAleatoria::EXITO;
}//abrirLectura

int ArchivoPalabraAleatoria::guardar(PalabraAleatoria* palabrasAleatorias, 
        unsigned int cantReg){
    
    if(!palabrasAleatorias)
        return BUFFER_NULO;
    if(!cantReg)
        return CANT_REG_NULO;
    if(!salida->is_open())
        return ARCH_NO_ABIERTO;
    
    const unsigned int TAM_BUFFER= PalabraAleatoria::TAM_REGISTRO*cantReg;
    salida->write((char*)palabrasAleatorias,TAM_BUFFER);
    if(salida->bad())
        return FALLA_ESCRITURA;
    
    this->posicionArchivo+= TAM_BUFFER;
    this->cantidadRegistros+= cantReg;
    
    return EXITO;
}//guardar

int ArchivoPalabraAleatoria::cargar(PalabraAleatoria* buffer, unsigned int &cantReg){
    
    if(!buffer){
        cantReg= 0;
        return BUFFER_NULO;
    }
    if(!cantReg)
        return CANT_REG_NULO;
    if(!entrada->is_open()){
        cantReg= 0;
        return ARCH_NO_ABIERTO;
    }
    if(entrada->eof()){
        cantReg= 0;
        return FIN_ARCHIVO;
    }
    
    unsigned long registroActual= this->posicionArchivo/PalabraAleatoria::TAM_REGISTRO;
    unsigned long registrosRestantes= this->cantidadRegistros- registroActual;
    if(cantReg>registrosRestantes)
        cantReg= registrosRestantes;
    
    const unsigned long TAM_BUFFER= cantReg*PalabraAleatoria::TAM_REGISTRO;
    entrada->read((char*)buffer,TAM_BUFFER);
    
    this->posicionArchivo+= TAM_BUFFER;
    
    if(entrada->eof())
        return FIN_ARCHIVO;
    
    return EXITO;
    
}//cargar

unsigned long ArchivoPalabraAleatoria::getCantidadRegistros(){
    return this->cantidadRegistros;
}//getCantidadRegistros

int ArchivoPalabraAleatoria::truncar(unsigned long cantReg){
    if(!cantReg)
        return CANT_REG_NULO;
    if(!salida->is_open() && !entrada->is_open())
        return ARCH_NO_ABIERTO;
    if(cantReg>this->cantidadRegistros)
        return EXITO;
    
    this->cerrar();
    
    const unsigned long TAM_NUEVO= cantReg*PalabraAleatoria::TAM_REGISTRO;
    truncate(this->pathArchivo,TAM_NUEVO);
    this->abrirLectura(pathArchivo);
    
    return EXITO;
}//truncar

int ArchivoPalabraAleatoria::limpiar(){
    if(!entrada->is_open() && !salida->is_open())
        return ARCH_NO_ABIERTO;
    
    this->cerrar();
    
    string comando= "rm ";
    comando+=pathArchivo;
    system(comando.c_str());
    comando= "touch ";
    comando+=pathArchivo;
    system(comando.c_str());
    
    this->abrirEscritura(pathArchivo);
}//limpiar

ArchivoPalabraAleatoria::ArchivoPalabraAleatoria(){
    this->entrada= new ifstream;
    this->salida= new ofstream;
    this->pathArchivo= new char[50];
    strcpy(pathArchivo,"***");
}//constructor

ArchivoPalabraAleatoria::~ArchivoPalabraAleatoria(){
    this->cerrar();
    delete salida;
    delete entrada;
    delete[] pathArchivo;
}//destructor